using System;
using System.Xml;
using System.Xml.Xsl;
using System.Drawing;
using System.IO;
using System.Web;
using System.Text;
using Waymex.Diagnostics;
using System.Globalization;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Waymex.Security;
using Waymex.Resources;
using Waymex.Xml;
using Waymex.Gis;
using Waymex.Gis.Coordinates;
using Waymex.Gis.Ellipsoids;
using Waymex.Gis.Projections;

[assembly: CLSCompliant(true)]
namespace Waymex.Gps
{
	/// <summary>
	/// This is the Base Class that all GPS device classes derive from.
	/// </summary>
    /// <example>C#
    /// <code>
    /// private void GetWaypoints(bool garmin)
    /// {
    ///     DeviceBase gps;
    ///
    ///     //Create a new device object depending on the type of GPS device
    ///     if (garmin)
    ///         gps = new GarminDevice();
    ///     else
    ///         gps = new MagellanDevice();
    ///
    ///     //Retrieve the Waypoints
    ///     WaypointCollection wpts = gps.GetWaypoints();
    /// 
    ///     //Now we have a collection of Waypoints
    ///     foreach (Waypoint wpt in wpts)
    ///     {
    ///         Console.WriteLine(wpt.Latitude);
    ///         Console.WriteLine(wpt.Longitude);
    ///     }
    ///
    ///     //Alternatively display the results in a DataGridView
    ///     dataGridView1.DataSource = wpts.ToDataSet();
    ///     dataGridView1.DataMember = "Waypoints";
    ///
    /// }
    /// </code>
    /// </example>

    //[LicenseProvider(typeof(RegistryLicenseProvider))]
#if(TRIAL)//need to fix GUID for PE as this is used during licencing
    [GuidAttribute("B6AF88C6-50DF-47ec-8CDB-5B7E9AF2A5DC")]
#endif
    public abstract class DeviceBase
	{
        //private License license = null;

        private LicenceStatus m_licenceStatus = LicenceStatus.licenceValid;

        //private const string INSTALLSHIELD_PRODUCT_CODE_TRIAL = "{271A284E-8913-45C0-862A-8687A329B7AC}";
        private const double TRIAL_EXPIRY_DAYS = 30.0;
        //these need moving out to a different namespace or making dynamic
        private const string PRODUCT_NAME = "GPS Library .Net";
        private const string PRODUCT_VERSION = "3.2";

        private const string EMBEDDED_KML_XSLT_FILE = "Gps.kml.xslt";

        private const string ERR_MSG_3010 = "The argument must be greater than zero.";
		private const string ERR_MSG_3011 = "The argument length must be greater than zero.";
		private const string ERR_MSG_3012 = "The file name must be between one and eight characters in length.";
		private const string ERR_MSG_3013 = "The folder name must be specified.";
		private const string ERR_MSG_3014 = "The argument is of range.";

        private const string ERR_MSG_LIC_NONEXISTENT = "The licence for this product is invalid or missing.";
        private const string ERR_MSG_LIC_EXPIRED = "The licence for this product has expired.";
	
		private const string MSG_PROPERTY_NOT_SUPPORTED = "The Property is not supported in by this device.";
		private const string MSG_METHOD_NOT_SUPPORTED = "The Method is not supported in by this device.";
        private const string MSG_METHOD_NOT_SUPPORTED_IN_PE = "The Method is not supported by this version of the product.";

        //http constants
		private const string HTTPSEND_WEBMETHOD = "PostGPSData";
		private const string HTTPSEND_PARAMETER_DATA = "strXMLData";
		private const string HTTPSEND_PARAMETER_DEVICEID  = "strDeviceID";
		private const string HTTPSEND_NAMESPACE = "http://www.waymex.co.uk/namespace/gps";

		private const double PI = 3.1415926535898;

		#region Public Events
		
        //.net 1.1
		//public virtual event ProgressEventHandler Progress;
		//public delegate void ProgressEventHandler(object sender, ProgressEventArgs e);

        /// <summary>
        /// The progress event fires during the data transfers to and from the GPS. 
        /// A long value of between 0 and 100 is passed to the event. 
        /// It is provided to allow a client application to display a progress 
        /// indicator during transfers.
        /// </summary>
        /// <example>C#
        /// <code><![CDATA[
        ///	// Register the event, typically in Form_Load
        ///	gps.Progress +=new EventHandler<ProgressEventArgs>(gps_Progress);
        /// 
        ///	private void gps_Progress(object sender, ProgressEventArgs e)
        ///	{
        ///		// Update a progress bar. This is OK as this event
        ///		// is raised on the thread that created the Device object.
        ///		pbProgress.Value = e.Progress;
        ///	}
        /// ]]></code>
        /// </example>
        public virtual event EventHandler<ProgressEventArgs> Progress;

		#endregion
        /// <summary>
        /// Constructor for DeviceBase.
        /// </summary>
        public DeviceBase()
        {
            //test code to test licence dll
            //bool IsValid = Waymex.Security.Licencing.GetLicence();

#if(TRIAL) // licencing only on trial
            try
            {
                m_licenceStatus = Waymex.Security.Licencing.GetLicenceStatus(PRODUCT_NAME, PRODUCT_VERSION, TRIAL_EXPIRY_DAYS);
                //m_licenceStatus = Waymex.Security.Licencing.GetLicenceStatus(typeof(Waymex.Gps.DeviceBase));
                //m_licenceStatus = Waymex.Security.Licencing.GetQlmLicenceStatus(typeof(Waymex.Gps.DeviceBase), 1, "GPS Library for .Net (2.0)", 3, 0, "{69C9C619-7226-4DF0-816D-3528133BC06F}");
                
                //make sure there is a valid licence
                if (m_licenceStatus == LicenceStatus.licenceNotValid)
                {
                    throw new ApplicationException(ERR_MSG_LIC_EXPIRED);
                }
                if (m_licenceStatus == LicenceStatus.licenceNonExistent)
                {
                    throw new ApplicationException(ERR_MSG_LIC_NONEXISTENT);
                }
                //license = LicenseManager.Validate(typeof(DeviceBase), this);
            }
            catch (Exception ex)
            {
                TraceLog.WriteError(ex);
                throw ex;
            }

#else
            m_licenceStatus = LicenceStatus.licenceValid;
#endif
        }
        //added when inheriting from component
        //protected override void Dispose(bool disposing)
        //{
        //    if (disposing)
        //    {
        //        if (license != null)
        //        {
        //            license.Dispose();
        //            license = null;
        //        }
        //    }

        //    base.Dispose(disposing);
        //}
		#region Public Virtual Method
		/// <summary>
		/// Returns a WaypointCollection object from the GPS device.
        /// </summary>
        /// <example>C#
		/// <code>
        /// private void GetWaypoints(bool garmin)
        /// {
        ///     DeviceBase gps;
        ///
        ///     //Create a new device object depending on the type of GPS device
        ///     if (garmin)
        ///         gps = new GarminDevice();
        ///     else
        ///         gps = new MagellanDevice();
        ///
        ///     //Retrieve the Waypoints
        ///     WaypointCollection wpts = gps.GetWaypoints();
        /// 
        ///     //Now we have a collection of Waypoints
        ///     foreach (Waypoint wpt in wpts)
        ///     {
        ///         Console.WriteLine(wpt.Latitude);
        ///         Console.WriteLine(wpt.Longitude);
        ///     }
        ///
        ///     //Alternatively display the results in a DataGridView
        ///     dataGridView1.DataSource = wpts.ToDataSet();
        ///     dataGridView1.DataMember = "Waypoints";
        ///
        /// }
        /// </code>
		/// </example>
        public virtual WaypointCollection GetWaypoints()
		{
			throw new NotSupportedException(MSG_METHOD_NOT_SUPPORTED);
		}
		/// <summary>
		/// Returns a RouteCollection of Route objects from the GPS Device. 
        /// </summary>
        /// <example>C#
		/// <code>
        /// private void GetRoutes(bool garmin)
        /// {
        ///     DeviceBase gps;
        ///
        ///     //Create a new device object depending on the type of GPS device
        ///     if (garmin)
        ///         gps = new GarminDevice();
        ///     else
        ///         gps = new MagellanDevice();
        ///
        ///     //Retrieve the Routes
        ///     RouteCollection rtes = gps.GetRoutes();
        ///
        ///     //Now we have a collection of Routes
        ///     foreach (Route rte in rtes)
        ///     {
        ///         Console.WriteLine(rte.Identifier);
        ///         Console.WriteLine(rte.Comment);
        ///
        ///         //Each Route has a collection of Waypoints
        ///         foreach (Waypoint wpt in rte.Waypoints)
        ///         {
        ///             Console.WriteLine(wpt.Latitude);
        ///             Console.WriteLine(wpt.Longitude);
        ///         }
        ///     }
        ///
        ///     //Alternatively display the results in a DataGridView
        ///     dataGridView1.DataSource = rtes.ToDataSet();
        ///     dataGridView1.DataMember = "Routes";
        ///
        /// }
		/// </code>
		/// </example>
        public virtual RouteCollection GetRoutes()
		{
			throw new NotSupportedException(MSG_METHOD_NOT_SUPPORTED);
		}
		/// <summary>
		/// Returns a TrackLogCollection of TrackLog objects from the GPS Device.
        /// </summary>
        /// <example>C#
        /// <code>
        /// private void GetTracklogs(bool garmin)
        /// {
        ///     DeviceBase gps;
        ///
        ///     //Create a new device object depending on the type of GPS device
        ///     if (garmin)
        ///         gps = new GarminDevice();
        ///     else
        ///         gps = new MagellanDevice();
        ///
        ///     //Retrieve the Tracklogs
        ///     TracklogCollection trks = gps.GetTracklogs();
        ///
        ///     //Now we have a collection of Tracklogs
        ///     foreach (Tracklog trk in trks)
        ///     {
        ///         Console.WriteLine(trk.Identifier);
        ///
        ///         //Each Tracklog has a collection of Trackpoints
        ///         foreach (Trackpoint tpt in trk.Trackpoints)
        ///         {
        ///             Console.WriteLine(tpt.Latitude);
        ///             Console.WriteLine(tpt.Longitude);
        ///         }
        ///     }
        ///
        ///     //Alternatively display the results in a DataGridView
        ///     dataGridView1.DataSource = trks.ToDataSet();
        ///     dataGridView1.DataMember = "Tracks";
        ///
        /// }
        /// </code>
        /// </example>

        public virtual TracklogCollection GetTracklogs()
		{
			throw new NotSupportedException(MSG_METHOD_NOT_SUPPORTED);
		}
		/// <summary>
        /// The SplitTracklog parameter when set to true returns multi-segment tracks
        /// as separate Tracklog objects. When set to false a multi-segment track is 
        /// returned as a single Tracklog object.
        /// </summary>
		/// <example>C#
		/// <code>
        /// private void GetTracklogs(bool garmin)
        /// {
        ///     DeviceBase gps;
        ///
        ///     //Create a new device object depending on the type of GPS device
        ///     if (garmin)
        ///         gps = new GarminDevice();
        ///     else
        ///         gps = new MagellanDevice();
        ///
        ///     //Retrieve the Tracklogs
        ///     TracklogCollection trks = gps.GetTracklogs();
        ///
        ///     //Now we have a collection of Tracklogs
        ///     foreach (Tracklog trk in trks)
        ///     {
        ///         Console.WriteLine(trk.Identifier);
        ///
        ///         //Each Tracklog has a collection of Trackpoints
        ///         foreach (Trackpoint tpt in trk.Trackpoints)
        ///         {
        ///             Console.WriteLine(tpt.Latitude);
        ///             Console.WriteLine(tpt.Longitude);
        ///         }
        ///     }
        ///
        ///     //Alternatively display the results in a DataGridView
        ///     dataGridView1.DataSource = trks.ToDataSet();
        ///     dataGridView1.DataMember = "Tracks";
        ///
        /// }
        /// </code>
		/// </example>
        public virtual TracklogCollection GetTracklogs(bool splitTracklog)
		{
			return GetTracklogs();
		}
        /// <summary>
        /// This method returns a Product info object containing information about the connected device.
        /// </summary>
        /// <returns>ProductInfo object</returns>
        public virtual ProductInfo GetProductInfo()
		{
			throw new NotSupportedException(MSG_METHOD_NOT_SUPPORTED);
		}
        /// <summary>
        /// Returns a AlmanacCollection object from the GPS Device.
        /// </summary>
        /// <example>C#
        /// <code>
        /// private void GetAlmanacs(bool garmin)
        /// {
        ///    DeviceBase gps;
        ///
        ///    //Create a new device object depending on the type of GPS device
        ///    if (garmin)
        ///        gps = new GarminDevice();
        ///    else
        ///        gps = new MagellanDevice();
        ///
        ///    //Retrieve the Almanacs
        ///    AlmanacCollection almacs = gps.GetAlmanacs();
        ///
        ///    //Now we have a collection of Almanacs
        ///    foreach (Almanac almc in almacs)
        ///    {
        ///        Console.WriteLine(almc.SatelliteId);
        ///        Console.WriteLine(almc.Health);
        ///    }
        ///
        ///    //Alternatively display the results in a DataGridView
        ///    dataGridView1.DataSource = almacs.ToDataSet();
        ///    dataGridView1.DataMember = "Almanacs";
        ///
        /// }
        /// </code>
        /// </example>
        public virtual AlmanacCollection GetAlmanacs()
		{
			throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
		}
        /// <summary>
        /// Gets/Sets the communications port to use.
        /// </summary>
		[Obsolete("Property depreciated. Use the OpenPort() and ClosePort() methods to set a communication port.")]
        public virtual Port CommunicationsPort
		{
			get
			{
				throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
			}
			set
			{
				throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
			}
		}
        /// <summary>
        /// Specifies and opens the serial communication port to use.
        /// </summary>
        /// <param name="port">The serial port to use. Values in the range 1 to 256 are accepted.</param>
        public virtual void OpenPort(int port)
        {
        	throw new NotSupportedException(MSG_METHOD_NOT_SUPPORTED);
        }
        
        /// <summary>
        /// Specifies and opens the serial communication port to use at the specified speed.
        /// </summary>
        /// <param name="port">Specifies the serial port to use. Values in the range 1 to 256 are accepted.</param>
        /// <param name="speed">Specifies the baud rate to use.</param>
        public virtual void OpenPort(int port, int speed)
        {
            throw new NotSupportedException(MSG_METHOD_NOT_SUPPORTED);
        }
        /// <summary>
        /// Opens the default port for the specific device. For example the default port for Garmin devices is the USB
        /// port, the default port for Magellan devices is COM 1.
        /// </summary>
        public virtual void OpenPort()
        {
            throw new NotSupportedException(MSG_METHOD_NOT_SUPPORTED);
        }

        /// <summary>
        /// Closes the currently open port. This can safely be called at any time.
        /// </summary>
        public virtual void ClosePort()
        {
            throw new NotSupportedException(MSG_METHOD_NOT_SUPPORTED);
        }

        /// <summary>
        /// Sets/Gets the Baud rate of the serial connection.
        /// Not applicable for USB connected devices.
        /// </summary>
        [Obsolete("Property depreciated. Use the OpenPort() and ClosePort() methods to set a communication port.")]
        public virtual BaudRate BaudRate
		{
			get
			{
				throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
			}
			set
			{
				throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
			}
		}
        /// <summary>
        /// Accepts a Waypoint object and transfers it to the connected GPS device.
        /// A value of True is returned if the transfer was successful.
        /// </summary>
        /// <example>C#
        /// <code>
        /// private void SetWaypoint(bool garmin)
        /// {
        ///
        ///     DeviceBase gps;
        ///     Waypoint newWpt = null;
        ///
        ///     //Create a new device object depending on the type of GPS device
        ///     if (garmin)
        ///         gps = new GarminDevice();
        ///     else
        ///         gps = new MagellanDevice();
        ///
        ///     //Create a Waypoint
        ///     newWpt = new Waypoint();
        ///     newWpt.Identifier = "Test01";
        ///     newWpt.Latitude = 53.9608166666667;
        ///     newWpt.Longitude = -2.02225;
        ///     newWpt.Comment = "Test 1";
        ///
        ///     //Transfer the Waypoint to the GPS device
        ///     gps.SetWaypoint(newWpt);
        ///
        /// }
        ///</code>
        ///</example>
        public virtual bool SetWaypoint(Waypoint waypoint)
		{
			throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
		}
        /// <summary>
        /// Accepts a WaypointCollection object and transfers them to the connected GPS device. 
        /// A value of True is returned if the transfer was successful.
        /// </summary>
        ///<example>C#
        /// <code>
        /// private void SetWaypoints(bool garmin)
        /// {
        ///     DeviceBase gps;
        ///     WaypointCollection newWpts = new WaypointCollection();
        ///     Waypoint newWpt = null;
        ///
        ///     //Create a new device object depending on the type of GPS device
        ///     if (garmin)
        ///         gps = new GarminDevice();
        ///     else
        ///         gps = new MagellanDevice();
        ///
        ///     //Create some Waypoints
        ///
        ///     //Waypoint 1
        ///     newWpt = new Waypoint();
        ///     newWpt.Identifier = "Test01";
        ///     newWpt.Latitude = 53.9608166666667;
        ///     newWpt.Longitude = -2.02225;
        ///     newWpt.Comment = "Test 1";
        ///
        ///     //Add the new waypoint to a Waypoint collection
        ///     newWpts.Add(newWpt);
        ///
        ///     //Waypoint 2
        ///     newWpt = new Waypoint();
        ///     newWpt.Identifier = "Test02";
        ///     newWpt.Latitude = 190.0;
        ///     newWpt.Longitude = 1180.0;
        ///     newWpt.Comment = "Test 2";
        ///
        ///     //Add the new Waypoint to a Waypoint collection
        ///     newWpts.Add(newWpt);
        ///
        ///     //Transfer the Waypoints to the GPS device
        ///     gps.SetWaypoints(newWpts);
        ///
        /// }
        /// </code>
        /// </example>
        public virtual bool SetWaypoints(WaypointCollection waypoints)
		{
			throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
		}
		/// <summary>
		/// Accepts a Route object and transfers it to the connected GPS device.
		/// A value of True is returned if the transfer was successful.
        /// </summary>
        /// <example>C#
		/// <code>
        /// private void SetRoute(bool garmin)
        /// {
        ///     DeviceBase gps;
        ///     Waypoint wpt;
        ///     Route rte;
        ///     WaypointCollection wpts;
        ///
        ///     //Create a new device object depending on the type of GPS device
        ///     if (garmin)
        ///         gps = new GarminDevice();
        ///     else
        ///         gps = new MagellanDevice();
        ///
        ///     //Create the collection of Waypoints for the Route
        ///     wpts = new WaypointCollection();
        ///
        ///     //Waypoint 1
        ///     wpt = new Waypoint();
        ///     wpt.Identifier = "RT01";
        ///     wpt.Latitude = 1.54;
        ///     wpt.Longitude = 0.2;
        ///
        ///     //Add the new Waypoint to the Waypoint Collection
        ///     wpts.Add(wpt);
        ///
        ///     //Waypoint 2
        ///     wpt = new Waypoint();
        ///     wpt.Identifier = "RT02";
        ///     wpt.Latitude = 1.53;
        ///     wpt.Longitude = 0.22;
        ///
        ///     //Add the new Waypoint to the Waypoint Collection
        ///     wpts.Add(wpt);
        ///
        ///     //Create and populate the Route
        ///     rte = new Route();
        ///     rte.Number = 2;
        ///     rte.Comment = "Hello Route";
        ///     rte.Waypoints = wpts;
        ///
        ///     //Transfer the Route to the GPS device
        ///     gps.SetRoute(rte);
        ///
        /// }
        /// </code>
		/// </example>
        public virtual bool SetRoute(Route route)
		{
			throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
		}
        /// <summary>
        /// Accepts a RouteCollection object and transfers it to the connected GPS device. 
        /// A value of True is returned if the transfer was successful.
        /// </summary>
        /// <example>C#
        /// <code>
        /// private void SetRoutes(bool garmin)
        /// {
        ///     DeviceBase gps;
        ///     Waypoint wpt;
        ///     Route rte;
        ///     RouteCollection rtes;
        ///     WaypointCollection wpts;
        ///
        ///     //Create a new device object depending on the type of GPS device
        ///     if (garmin)
        ///         gps = new GarminDevice();
        ///     else
        ///         gps = new MagellanDevice();
        ///
        ///     //Create the collection of Waypoints for the Route
        ///     wpts = new WaypointCollection();
        ///
        ///     //Waypoint 1
        ///     wpt = new Waypoint();
        ///     wpt.Identifier = "RT01";
        ///     wpt.Latitude = 1.54;
        ///     wpt.Longitude = 0.2;
        ///
        ///     //Add the new Waypoint to the Waypoint Collection
        ///     wpts.Add(wpt);
        ///
        ///     //Waypoint 2
        ///     wpt = new Waypoint();
        ///     wpt.Identifier = "RT02";
        ///     wpt.Latitude = 1.53;
        ///     wpt.Longitude = 0.22;
        ///
        ///     //Add the new Waypoint to the Waypoint Collection
        ///     wpts.Add(wpt);
        ///
        ///     //Create and populate the Route
        ///     rte = new Route();
        ///     rte.Number = 2;
        ///     rte.Comment = "Hello Route";
        ///     rte.Waypoints = wpts;
        ///
        ///     //Create a routes collection 
        ///     //Typically a single Route would be transferred using SetRoute
        ///     rtes = new RouteCollection();
        ///     rtes.Add(rte);
        ///
        ///     //Transfer the Routes to the GPS device
        ///     gps.SetRoutes(rtes);
        ///
        /// }
        /// </code>
        /// </example>
        public virtual bool SetRoutes(RouteCollection routes)
		{
			throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
		}
		/// <summary>
		/// Accepts a Tracklog object and transfers it to the connected GPS device.
        /// A value of True is returned if the transfer was successful.
        /// </summary>
        /// <example>C#
        /// <code>
        /// public void SetTracklog(bool garmin)
        /// {
        ///     DeviceBase gps;
        ///     Tracklog trk;
        ///     Trackpoint tpt;
        ///
        ///     //Create a new device object depending on the type of GPS device
        ///     if (garmin)
        ///         gps = new GarminDevice();
        ///     else
        ///         gps = new MagellanDevice();
        ///
        ///     //Create a new Tracklog object
        ///     trk = new Tracklog();
        ///     trk.Identifier = "Upload";
        ///
        ///     //Create the first Trackpoint
        ///     tpt = new Trackpoint();
        ///     tpt.Longitude = 146.42;
        ///     tpt.Latitude = -36.47;
        ///     tpt.NewTrack = true;
        ///     trk.Trackpoints.Add(tpt);
        ///
        ///     //Create a second Trackpoint
        ///     tpt = new Trackpoint();
        ///     tpt.Longitude = 146.43;
        ///     tpt.Latitude = -36.48;
        ///     trk.Trackpoints.Add(tpt);
        ///
        ///     //Create the third Trackpoint
        ///     tpt = new Trackpoint();
        ///     tpt.Longitude = 146.44;
        ///     tpt.Latitude = -36.49;
        ///     tpt.NewTrack = true;
        ///     trk.Trackpoints.Add(tpt);
        ///
        ///     //Create the fourth Trackpoint
        ///     tpt = new Trackpoint();
        ///     tpt.Longitude = 146.45;
        ///     tpt.Latitude = -36.5;
        ///     trk.Trackpoints.Add(tpt);
        ///
        ///     //Send the Tracklog to the GPS device
        ///     gps.SetTrackLog(trk);
        ///
        /// }
        /// </code>
        /// </example>
        public virtual bool SetTrackLog(Tracklog tracklog)
		{
			throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
		}
        /// <summary>
        /// The SplitTracklog parameter, when set to true allows a multi-segment
        /// Tracklog object to be transferred to the GPS as multiple tracklogs.
        /// A setting of false ensures a multi-segment Tracklog object is transferred
        /// to the GPS device as a single track.
        /// </summary>
        /// <example>C#
        /// <code>
        /// public void SetTracklog(bool garmin)
        /// {
        ///     DeviceBase gps;
        ///     Tracklog trk;
        ///     Trackpoint tpt;
        ///
        ///     //Create a new device object depending on the type of GPS device
        ///     if (garmin)
        ///         gps = new GarminDevice();
        ///     else
        ///         gps = new MagellanDevice();
        ///
        ///     //Create a new Tracklog object
        ///     trk = new Tracklog();
        ///     trk.Identifier = "Upload";
        ///
        ///     //Create the first Trackpoint
        ///     tpt = new Trackpoint();
        ///     tpt.Longitude = 146.42;
        ///     tpt.Latitude = -36.47;
        ///     tpt.NewTrack = true;
        ///     trk.Trackpoints.Add(tpt);
        ///
        ///     //Create a second Trackpoint
        ///     tpt = new Trackpoint();
        ///     tpt.Longitude = 146.43;
        ///     tpt.Latitude = -36.48;
        ///     trk.Trackpoints.Add(tpt);
        ///
        ///     //Create the third Trackpoint
        ///     tpt = new Trackpoint();
        ///     tpt.Longitude = 146.44;
        ///     tpt.Latitude = -36.49;
        ///     tpt.NewTrack = true;
        ///     trk.Trackpoints.Add(tpt);
        ///
        ///     //Create the fourth Trackpoint
        ///     tpt = new Trackpoint();
        ///     tpt.Longitude = 146.45;
        ///     tpt.Latitude = -36.5;
        ///     trk.Trackpoints.Add(tpt);
        ///
        ///     //Send the Tracklog to the GPS device
        ///     gps.SetTrackLog(trk);
        ///
        /// }
        /// </code>
        /// </example>
		public virtual bool SetTrackLog(Tracklog tracklog, bool splitTracklog)
		{
			throw new NotSupportedException(MSG_PROPERTY_NOT_SUPPORTED);
		}

		#endregion

//        #region HttpSend Methods

//        /// <summary>
//        /// Transfers GPS data to the Waymex GPS Web Service. 
//        /// The strURL parameter should be set to the URL of the Web Service
//        /// The strDeviceID can be used identify the device/user etc as required. 
//        /// The value of this parameter will be assigned to the 'deviceid' attribute 
//        /// of the root node of the resulting XML at the web server.
//        /// A value of True is returned if the transfer was successful.
//        /// </summary>
//        /// <remarks>
//        /// The Waymex GPS Web Service is a freely available web service that can 
//        /// be installed on a suitable server. Once configured Positional information, 
//        /// Tracklog data, Waypoints and Route information can be transferred over 
//        /// the internet very simply using the GPS Library.
//        /// The Web Service accepts data over http from the GPS Library and stores 
//        /// it in XML files on the web server in a suitable directory (configurable). 
//        /// These files can then be processed as required by other systems.
//        /// The Web Service requires the .Net Framework Version 1.1. 
//        /// </remarks>
//        internal static bool HttpSend(System.Uri uri, WaypointCollection waypoints, string deviceId)
//        {
//            bool blnResult = false;
//            try
//            {
//                Waymex.Gps.Web.GPSDataWS objWebService = new Waymex.Gps.Web.GPSDataWS();
//                objWebService.Url = uri.AbsoluteUri;
//                blnResult = objWebService.PostGPSData(waypoints.ToXml(), deviceId);
//            }

//            catch(Exception e)
//            {
//                throw new HttpTransferException(e.Message, e);
//            }

//            return blnResult;
//        }
//        /// <summary>
//        /// Transfers GPS data to the Waymex GPS Web Service. 
//        /// The strURL parameter should be set to the URL of the Web Service
//        /// The strDeviceID can be used identify the device/user etc as required. 
//        /// The value of this parameter will be assigned to the 'deviceid' attribute 
//        /// of the root node of the resulting XML at the web server.
//        /// A value of True is returned if the transfer was successful.
//        /// </summary>
//        /// <remarks>
//        /// The Waymex GPS Web Service is a freely available web service that can 
//        /// be installed on a suitable server. Once configured Positional information, 
//        /// Tracklog data, Waypoints and Route information can be transferred over 
//        /// the internet very simply using the GPS Library.
//        /// The Web Service accepts data over http from the GPS Library and stores 
//        /// it in XML files on the web server in a suitable directory (configurable). 
//        /// These files can then be processed as required by other systems.
//        /// The Web Service requires the .Net Framework Version 1.1. 
//        /// </remarks>
//        internal static bool HttpSend(System.Uri uri, Position position, string deviceId)
//        {
//            bool blnResult = false;
//            try
//            {
//                Waymex.Gps.Web.GPSDataWS objWebService = new Waymex.Gps.Web.GPSDataWS();
//                objWebService.Url = uri.AbsoluteUri;
//                blnResult = objWebService.PostGPSData(position.ToXml(), deviceId);
//            }

//            catch(Exception e)
//            {
//                throw new HttpTransferException(e.Message, e);
//            }

//            return blnResult;
//        }
//        /// <summary>
//        /// Transfers GPS data to the Waymex GPS Web Service. 
//        /// The strURL parameter should be set to the URL of the Web Service
//        /// The strDeviceID can be used identify the device/user etc as required. 
//        /// The value of this parameter will be assigned to the 'deviceid' attribute 
//        /// of the root node of the resulting XML at the web server.
//        /// A value of True is returned if the transfer was successful.
//        /// </summary>
//        /// <remarks>
//        /// The Waymex GPS Web Service is a freely available web service that can 
//        /// be installed on a suitable server. Once configured Positional information, 
//        /// Tracklog data, Waypoints and Route information can be transferred over 
//        /// the internet very simply using the GPS Library.
//        /// The Web Service accepts data over http from the GPS Library and stores 
//        /// it in XML files on the web server in a suitable directory (configurable). 
//        /// These files can then be processed as required by other systems.
//        /// The Web Service requires the .Net Framework Version 1.1. 
//        /// </remarks>
//        internal static bool HttpSend(System.Uri uri, Tracklog tracklog, string deviceId)
//        {
//            bool blnResult = false;
//            try
//            {
//                Waymex.Gps.Web.GPSDataWS objWebService = new Waymex.Gps.Web.GPSDataWS();
//                objWebService.Url = uri.AbsoluteUri;
//                blnResult = objWebService.PostGPSData(tracklog.ToXml(), deviceId);
//            }

//            catch(Exception e)
//            {
//                throw new HttpTransferException(e.Message, e);
//            }

//            return blnResult;
//        }
//        /// <summary>
//        /// Transfers GPS data to the Waymex GPS Web Service. 
//        /// The strURL parameter should be set to the URL of the Web Service
//        /// The strDeviceID can be used identify the device/user etc as required. 
//        /// The value of this parameter will be assigned to the 'deviceid' attribute 
//        /// of the root node of the resulting XML at the web server.
//        /// A value of True is returned if the transfer was successful.
//        /// </summary>
//        /// <remarks>
//        /// The Waymex GPS Web Service is a freely available web service that can 
//        /// be installed on a suitable server. Once configured Positional information, 
//        /// Tracklog data, Waypoints and Route information can be transferred over 
//        /// the internet very simply using the GPS Library.
//        /// The Web Service accepts data over http from the GPS Library and stores 
//        /// it in XML files on the web server in a suitable directory (configurable). 
//        /// These files can then be processed as required by other systems.
//        /// The Web Service requires the .Net Framework Version 1.1. 
//        /// </remarks>
//        internal static bool HttpSend(System.Uri uri, Route route, string deviceId)
//        {
//            bool blnResult = false;
//            try
//            {
//                Waymex.Gps.Web.GPSDataWS objWebService = new Waymex.Gps.Web.GPSDataWS();
//                objWebService.Url = uri.AbsoluteUri;
//                blnResult = objWebService.PostGPSData(route.ToXml(), deviceId);
//            }

//            catch(Exception e)
//            {
//                throw new HttpTransferException(e.Message, e);
//            }
//            return blnResult;

//        }

//        #endregion

		#region Shape Methods
        /// <summary>
        /// This method is obsolete please use the following method instead: <code>public void SaveToShape(RouteCollection routes, string folder, string fileName, Waymex.Gis.Shape.Projection projection)</code>
        /// </summary>
        /// <param name="routes"></param>
        /// <param name="folder"></param>
        /// <param name="fileName"></param>
        /// <param name="projection"></param>
        [Obsolete("This method is obsolete please use the following method instead: public void SaveToShape(RouteCollection routes, string folder, string fileName, Waymex.Gis.Shape.Projection projection)")]
        public void SaveToShape(RouteCollection routes, string folder, string fileName, Waymex.Gis.Projection projection)
        {
            try
            {
                //covert the coordinates if required
                if (projection == Waymex.Gis.Projection.Utm)
                {
                    SaveToShape(routes, folder, fileName, Waymex.Gis.Shape.Projection.Utm);
                }
                else
                {
                    SaveToShape(routes, folder, fileName, Waymex.Gis.Shape.Projection.Geographic);
                }
            }
            catch (Exception ex)
            {
                //just re-throw as this will be a shape exception
                throw;
            }
        }
        /// <summary>
        /// This method allows GPS data to be saved as an ESRI Shape
        /// file. The method creates the Main, Index and Attribute files
        /// in the specified directory.
        /// The directory specified will be created if it does not already exist. 
        /// Shape files can be saved using either Geographic coordinates, (i.e. where 
        /// the Latitude and Longitude are the X, Y values), or Utm coordinates.
        /// </summary>
        public void SaveToShape(RouteCollection routes, string folder, string fileName, Waymex.Gis.Shape.Projection projection)
		{
            try
            {
                //convert points if required
                switch (projection)
                {
                    case Waymex.Gis.Shape.Projection.Utm:
                        foreach (Route objRoute in routes)
                        {
                            foreach (Waypoint objWaypoint in objRoute.Waypoints)
                            {
                                Waymex.Gis.Coordinates.EastingNorthingCoordinates eastingNorthing = Waymex.Gis.Convert.ToEastingNorthing(new Wgs84Ellipsoid(), new UtmProjection(objWaypoint.Latitude, objWaypoint.Longitude), new LatitudeLongitudeCoordinates(objWaypoint.Latitude, objWaypoint.Longitude));
                                objWaypoint.X = eastingNorthing.Easting;
                                objWaypoint.X = eastingNorthing.Northing;

                                objWaypoint.Transformed = true;
                            }
                        }
                        break;
                }
                SaveToShape(routes, folder, fileName);
            }
            catch (Exception ex)
            {
                //just re-throw as this will be a shape exception
                throw ex;
            }

		}
		private void SaveToShape(RouteCollection routes, string folder, string fileName)
		{
			try
			{
                if (fileName.Length < 1 || fileName.Length > 8)
				{
					throw new InvalidFileName(ERR_MSG_3012);
				}
                if (folder.Length == 0)
				{
                    throw new InvalidFileName(ERR_MSG_3013);
				}

				//create the shape file and the polyline
				Gis.Shape.ShapeFile objShapefile = new Gis.Shape.ShapeFile();

				//run through each route
				foreach(Route objRoute in routes)
				{
					Gis.Shape.PolyLine objPolyline = new Waymex.Gis.Shape.PolyLine();
				
					//create the attributes collection
					Gis.Shape.Attributes objAttributes = new Waymex.Gis.Shape.Attributes();
				
					//add the attributes from the tracklog
					objAttributes.Append(new Gis.Shape.Attribute("NMBR",objRoute.Number));
					objAttributes.Append(new Gis.Shape.Attribute("IDENTIFIER",CharacterSetTrimForShape(objRoute.Identifier)));
					objAttributes.Append(new Gis.Shape.Attribute("COMMENT",CharacterSetTrimForShape(objRoute.Comment)));

					foreach(Waypoint objWaypoint in objRoute.Waypoints)
					{
						Gis.Shape.Point objPoint = new Waymex.Gis.Shape.Point();

						//add the trackpoints to the shape
						if(objWaypoint.Transformed)
						{
							objPoint.ValueX = objWaypoint.X;
							objPoint.ValueY = objWaypoint.Y;
						}
						else
						{
							objPoint.ValueX = objWaypoint.Longitude;
							objPoint.ValueY = objWaypoint.Latitude;
						}
						objPolyline.AddPoint(objPoint,false);
					}

					//add shape to the shapefile
					objShapefile.AppendShape(objPolyline,objAttributes);
				}

				//save shape to disk
                objShapefile.Save(folder, fileName);

			}
			catch(Exception ex)
			{
                //just re-throw as this will be a shape exception
                throw ex;
            }
		}
		private void SaveToShape(TracklogCollection tracklogs, string folder, string fileName)
		{
			
			try
			{

                if (fileName.Length < 1 || fileName.Length > 8)
				{
                    throw new InvalidFileName(ERR_MSG_3012);
				}
                if (folder.Length == 0)
				{
                    throw new InvalidFileName(ERR_MSG_3013);
				}

				
				//create the shape file and the polyline
				Gis.Shape.ShapeFile objShapefile = new Gis.Shape.ShapeFile();

				foreach(Tracklog objTracklog in tracklogs)
				{
					Gis.Shape.PolyLine objPolyline = new Waymex.Gis.Shape.PolyLine();
				
					//create the attributes collection
					Gis.Shape.Attributes objAttributes = new Waymex.Gis.Shape.Attributes();
				
					//add the attributes from the tracklog
					if(objTracklog.Identifier != null)
					{
						objAttributes.Append(new Gis.Shape.Attribute("IDENTIFIER",CharacterSetTrimForShape(objTracklog.Identifier)));
					}
					else
					{
						objAttributes.Append(new Gis.Shape.Attribute("IDENTIFIER",""));
					}
					objAttributes.Append(new Gis.Shape.Attribute("DISPLAY",objTracklog.Display.ToString(CultureInfo.InvariantCulture)));
					objAttributes.Append(new Gis.Shape.Attribute("COLOUR",objTracklog.Colour));

					foreach(Trackpoint objTrackpoint in objTracklog.Trackpoints)
					{
						Gis.Shape.Point objPoint = new Waymex.Gis.Shape.Point();

						if(objTrackpoint.Transformed)
						{
							//add the trackpoints to the shape
							objPoint.ValueX = objTrackpoint.X;
							objPoint.ValueY = objTrackpoint.Y;
						}
						else
						{
							//add the trackpoints to the shape
							objPoint.ValueX = objTrackpoint.Longitude;
							objPoint.ValueY = objTrackpoint.Latitude;
						}
						objPolyline.AddPoint(objPoint,false);
					}

					//add shape to the shapefile
					objShapefile.AppendShape(objPolyline,objAttributes);
				}

				//save shape to disk
				objShapefile.Save(folder, fileName);

			}
			catch(Exception ex)
			{
                //just re-throw as this will be a shape exception
                throw ex;
            }

		}

        /// <summary>
        /// This method is obsolete please use the following method instead: <code>public void SaveToShape(TracklogCollection tracklogs, string folder, string fileName, Waymex.Gis.Shape.Projection projection)</code>
        /// </summary>
        /// <param name="tracklogs"></param>
        /// <param name="folder"></param>
        /// <param name="fileName"></param>
        /// <param name="projection"></param>
        [Obsolete("This method is obsolete please use the following method instead: <code>public void SaveToShape(TracklogCollection tracklogs, string folder, string fileName, Waymex.Gis.Shape.Projection projection)")]
        public void SaveToShape(TracklogCollection tracklogs, string folder, string fileName, Waymex.Gis.Projection projection)
        {
            try
            {
                //covert the coordinates if required
                if (projection == Waymex.Gis.Projection.Utm)
                {
                    SaveToShape(tracklogs, folder, fileName, Waymex.Gis.Shape.Projection.Utm);
                }
                else
                {
                    SaveToShape(tracklogs, folder, fileName, Waymex.Gis.Shape.Projection.Geographic);
                }
            }
            catch (Exception ex)
            {
                //just re-throw as this will be a shape exception
                throw;
            }
        }
        /// <summary>
        /// This method allows GPS data to be saved as an ESRI Shape
        /// file. The method creates the Main, Index and Attribute files
        /// in the specified directory.
        /// The directory specified will be created if it does not already exist. 
        /// Shape files can be saved using either Geographic coordinates, (i.e. where 
        /// the Latitude and Longitude are the X, Y values), or Utm coordinates.
        /// </summary>
        public void SaveToShape(TracklogCollection tracklogs, string folder, string fileName, Waymex.Gis.Shape.Projection projection)
		{
			try
			{
				//covert the coordinates if required
                switch (projection)
				{
                    case Waymex.Gis.Shape.Projection.Utm:
                        foreach (Tracklog objTrack in tracklogs)
						{
							foreach(Trackpoint objTrackpoint in objTrack.Trackpoints)
							{
                                Waymex.Gis.Coordinates.EastingNorthingCoordinates eastingNorthing = Waymex.Gis.Convert.ToEastingNorthing(new Wgs84Ellipsoid(), new UtmProjection(objTrackpoint.Latitude, objTrackpoint.Longitude), new LatitudeLongitudeCoordinates(objTrackpoint.Latitude, objTrackpoint.Longitude));
                                objTrackpoint.X = eastingNorthing.Easting;
                                objTrackpoint.X = eastingNorthing.Northing;
                                
                                objTrackpoint.Transformed = true;
							}
						}
						break;
				}

				SaveToShape(tracklogs, folder, fileName);
			}
			catch(Exception ex)
			{
                //just re-throw as this will be a shape exception
                throw ex;
            }

		}
        /// <summary>
        /// This method is obsolete please use the following method instead: <code>public void SaveToShape(WaypointCollection waypoints, string folder, string fileName, Waymex.Gis.Shape.Projection projection)</code>
        /// </summary>
        /// <param name="waypoints"></param>
        /// <param name="folder"></param>
        /// <param name="fileName"></param>
        /// <param name="projection"></param>
        [Obsolete("This method is obsolete please use the following method instead: <code>public void SaveToShape(WaypointCollection waypoints, string folder, string fileName, Waymex.Gis.Shape.Projection projection)")]
        public void SaveToShape(WaypointCollection waypoints, string folder, string fileName, Waymex.Gis.Projection projection)
        {
            try
            {
                //covert the coordinates if required
                if (projection == Waymex.Gis.Projection.Utm)
                {
                        SaveToShape(waypoints,folder,fileName,Waymex.Gis.Shape.Projection.Utm);
                }
                else
                {
                        SaveToShape(waypoints,folder,fileName,Waymex.Gis.Shape.Projection.Geographic);
                }
            }
            catch (Exception ex)
            {
                //just re-throw as this will be a shape exception
                throw;
            }
        }
        /// <summary>
        /// This method allows GPS data to be saved as an ESRI Shape
        /// file. The method creates the Main, Index and Attribute files
        /// in the specified directory.
        /// The directory specified will be created if it does not already exist. 
        /// Shape files can be saved using either Geographic coordinates, (i.e. where 
        /// the Latitude and Longitude are the X, Y values), or Utm coordinates.
        /// </summary>
        public void SaveToShape(WaypointCollection waypoints, string folder, string fileName, Waymex.Gis.Shape.Projection projection)
		{
			try
			{
				//covert the coordinates if required
                switch (projection)
				{
                    case Waymex.Gis.Shape.Projection.Utm:

                        foreach (Waypoint objWaypoint in waypoints)
						{                            
                            Waymex.Gis.Coordinates.EastingNorthingCoordinates eastingNorthing = Waymex.Gis.Convert.ToEastingNorthing(new Wgs84Ellipsoid(), new UtmProjection(objWaypoint.Latitude, objWaypoint.Longitude), new LatitudeLongitudeCoordinates(objWaypoint.Latitude, objWaypoint.Longitude));
                            objWaypoint.X = eastingNorthing.Easting;
                            objWaypoint.X = eastingNorthing.Northing;

                            objWaypoint.Transformed = true;
						}
						break;
				}

				SaveToShape(waypoints, folder, fileName);

			}
			catch(Exception ex)
			{
                //just re-throw as this will be a shape exception
                throw;
            }

		}
		private void SaveToShape(WaypointCollection waypoints, string folder, string fileName)
		{
			try
			{
                if (fileName.Length < 1 || fileName.Length > 8)
				{
                    throw new InvalidFileName(ERR_MSG_3012);
				}
                if (folder.Length == 0)
				{
                    throw new InvalidFileName(ERR_MSG_3013);
				}


				//create the shape file and the polyline
				Gis.Shape.ShapeFile objShapefile = new Gis.Shape.ShapeFile();
				
				foreach(Waypoint objWaypoint in waypoints)
				{

					//create the attributes collection
					Gis.Shape.Attributes objAttributes = new Waymex.Gis.Shape.Attributes();
				
					//add the attributes from the tracklog
					objAttributes.Append(new Gis.Shape.Attribute("NMBR",CharacterSetTrimForShape(objWaypoint.Identifier)));
					if(objWaypoint.Transformed)
					{
						objAttributes.Append(new Gis.Shape.Attribute("Y",objWaypoint.Y));
						objAttributes.Append(new Gis.Shape.Attribute("X",objWaypoint.X));
					}
					else
					{
						objAttributes.Append(new Gis.Shape.Attribute("Y",objWaypoint.Latitude));
						objAttributes.Append(new Gis.Shape.Attribute("X",objWaypoint.Longitude));
					}

					objAttributes.Append(new Gis.Shape.Attribute("COMMENT",CharacterSetTrimForShape(objWaypoint.Comment)));
					objAttributes.Append(new Gis.Shape.Attribute("SYMBOL",objWaypoint.Symbol));
					objAttributes.Append(new Gis.Shape.Attribute("ICON",CharacterSetTrimForShape(objWaypoint.Icon)));
					objAttributes.Append(new Gis.Shape.Attribute("COLOUR",objWaypoint.Colour));
					objAttributes.Append(new Gis.Shape.Attribute("DISPLAY",objWaypoint.Display));
					objAttributes.Append(new Gis.Shape.Attribute("PROX_DIST",objWaypoint.ProximityDistance));
					objAttributes.Append(new Gis.Shape.Attribute("PROX_INDEX",objWaypoint.ProximityIndex));
					objAttributes.Append(new Gis.Shape.Attribute("ALTITUDE",objWaypoint.Altitude));
					objAttributes.Append(new Gis.Shape.Attribute("DEPTH",objWaypoint.Depth));
					objAttributes.Append(new Gis.Shape.Attribute("CLASS",objWaypoint.Class));
					objAttributes.Append(new Gis.Shape.Attribute("ATTRIBUTES",objWaypoint.Attributes));
					objAttributes.Append(new Gis.Shape.Attribute("LINK",CharacterSetTrimForShape(objWaypoint.Link)));
					objAttributes.Append(new Gis.Shape.Attribute("STATE",CharacterSetTrimForShape(objWaypoint.State)));
					objAttributes.Append(new Gis.Shape.Attribute("COUNTRY",CharacterSetTrimForShape(objWaypoint.Country)));
					objAttributes.Append(new Gis.Shape.Attribute("CITY",CharacterSetTrimForShape(objWaypoint.City)));
					objAttributes.Append(new Gis.Shape.Attribute("ADDRESS",CharacterSetTrimForShape(objWaypoint.Address)));
					objAttributes.Append(new Gis.Shape.Attribute("FACILITY",CharacterSetTrimForShape(objWaypoint.Facility)));
					objAttributes.Append(new Gis.Shape.Attribute("ROAD",CharacterSetTrimForShape(objWaypoint.Crossroad)));
					objAttributes.Append(new Gis.Shape.Attribute("PKT_TYPE",objWaypoint.PacketType));
					objAttributes.Append(new Gis.Shape.Attribute("TIME_ENRTE",objWaypoint.TimeENRoute));
					
					Gis.Shape.Point objPoint = new Waymex.Gis.Shape.Point();

					if(objWaypoint.Transformed)
					{
						//add the trackpoints to the shape
						objPoint.ValueX = objWaypoint.X;
						objPoint.ValueY = objWaypoint.Y;
					}
					else
					{
						//add the trackpoints to the shape
						objPoint.ValueX = objWaypoint.Longitude;
						objPoint.ValueY = objWaypoint.Latitude;
					}
					//add shape to the shapefile
					objShapefile.AppendShape(objPoint,objAttributes);
				}

				//save shape to disk
				objShapefile.Save(folder, fileName);

			}
			catch(Exception ex)
			{
                //just re-throw as this will be a shape exception
                throw;
            }
		}


		#endregion

        #region KML Methods

        /// <summary>
        /// This method allows GPS data to be saved as a Google Earth Kml
        /// file. The method creates the file in the specified folder.
        /// The folder specified will be created if it does not already exist
        /// and if the file already exisits it will be overwritten.
        /// </summary>
        public void SaveToKml(WaypointCollection waypoints, string folder, string filename, Color color)
        {
            //int width = 4; //not used on Waypoints
            string xml = waypoints.ToXml();
            string colour =
                color.A.ToString("X2") +
                color.R.ToString("X2") +
                color.G.ToString("X2") +
                color.B.ToString("X2");

            XsltArgumentList xsltArgs = new XsltArgumentList();
            xsltArgs.AddParam("lineColor", "", colour);
            xsltArgs.AddParam("polyColor", "", colour);
            //xsltArgs.AddParam("lineWidth", "", width);

            using (Stream stream = ResourceManager.GetEmbeddedResource(EMBEDDED_KML_XSLT_FILE))
            {
                String kml = Waymex.Xml.Transform.XsltTransform(xml, stream, xsltArgs, Waymex.Xml.Transform.OutputType.Xml);
                File.WriteAllText(CreateValidFilename(folder, filename), kml);
            }
        }
        /// <summary>
        /// This method allows GPS data to be saved as a Google Earth Kml
        /// file. The method creates the file in the specified folder.
        /// The folder specified will be created if it does not already exist
        /// and if the file already exisits it will be overwritten.
        /// </summary>
        public void SaveToKml(RouteCollection routes, string folder, string filename, Color color, int width)
        {
            string xml = routes.ToXml();
            string colour =
                color.A.ToString("X2") +
                color.R.ToString("X2") +
                color.G.ToString("X2") +
                color.B.ToString("X2");

            XsltArgumentList xsltArgs = new XsltArgumentList();
            xsltArgs.AddParam("lineColor", "", colour);
            xsltArgs.AddParam("polyColor", "", colour);
            xsltArgs.AddParam("lineWidth", "", width);

            using (Stream stream = ResourceManager.GetEmbeddedResource(EMBEDDED_KML_XSLT_FILE))
            {
                String kml = Waymex.Xml.Transform.XsltTransform(xml, stream, xsltArgs, Waymex.Xml.Transform.OutputType.Xml);
                File.WriteAllText(CreateValidFilename(folder, filename), kml);
            }
        }
        /// <summary>
        /// This method allows GPS data to be saved as a Google Earth Kml
        /// file. The method creates the file in the specified folder.
        /// The folder specified will be created if it does not already exist
        /// and if the file already exisits it will be overwritten.
        /// </summary>
        public void SaveToKml(TracklogCollection tracklogs, string folder, string filename, Color color, int width)
        {
            string xml = tracklogs.ToXml();
            string colour = 
                color.A.ToString("X2") + 
                color.R.ToString("X2") + 
                color.G.ToString("X2") + 
                color.B.ToString("X2");
            
            XsltArgumentList xsltArgs = new XsltArgumentList();
            xsltArgs.AddParam("lineColor", "", colour);
            xsltArgs.AddParam("polyColor", "", colour);
            xsltArgs.AddParam("lineWidth", "", width);

            using (Stream stream = ResourceManager.GetEmbeddedResource(EMBEDDED_KML_XSLT_FILE))
            {
                String kml = Waymex.Xml.Transform.XsltTransform(xml, stream, xsltArgs, Waymex.Xml.Transform.OutputType.Xml);
                File.WriteAllText(CreateValidFilename(folder, filename), kml);
            }
        }
        #endregion

        #region Properties
        
        internal LicenceStatus Licence
        {
            get
            {
                return m_licenceStatus;
            }
        }
        #endregion

        #region Private Methods

        /// <summary>
        /// Tidies up the filename and ensures that the specified 
        /// folder is created if it doesn't exist
        /// </summary>
        /// <param name="folder"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private string CreateValidFilename(string folder, string fileName)
        {
            //check the filename
            if (fileName.Length < 1)
            {
                throw new InvalidFileName(ERR_MSG_3012);
            }
            if (folder.Length == 0)
            {
                throw new InvalidFileName(ERR_MSG_3013);
            }

            //determine if folder exists
            if (!Directory.Exists(folder))
            {
                Directory.CreateDirectory(folder);
            }

            if (!folder.EndsWith(@"\\"))
                folder = folder + @"\";

            return folder + fileName;
        }

        private string CharacterSetTrimForShape(string sData)
		{
			//-------------------------------------------------------------------------
			// ABSTRACT:     This function limits the character string and is used
			//               when creating shape files.
			//
			// PARAMETERS:
			//
			// RETURNS:
			//
			// DESCRIPTION:
			//
			//-------------------------------------------------------------------------
			//
			//    'UCase letters 65-90
			//    'LCase letters 97-122
			//    'numbers 48 - 57
			//    'hyphen 45
			//    'space 32

			int iChar = 0;
			string sOut = "";

			try
			{
				if(sData == null)
					sData = "";

				if(sData.Length > 0)
				{
					//upper/lower case letters numbers spaces and hyphen
					for(int f = 1; f <= sData.Length; f++)
					{
						iChar = Microsoft.VisualBasic.Strings.Asc(sData.Substring(f - 1, 1));
						if((iChar >= 65 && iChar <= 90) || (iChar >= 48 && iChar <= 57) || iChar == 32 || iChar == 45)
							//sOut = sOut & Chr(iChar);																		  
							sOut = string.Concat(sOut, Microsoft.VisualBasic.Strings.Chr(iChar));																		  
					}
				}			
					
			}
			catch(Exception ex)
			{
				throw ex;
			}
			return sOut;
		}
		

		#endregion

		#region Internal Methods
		/// <summary>
		/// Raises the value specified in Value to the power specified in Power.
		/// </summary>
		/// <param name="Value"></param>
		/// <param name="Power"></param>
		/// <returns></returns>
		internal double RaiseToPower(double Value, double Power)
		{
			double Retval = Value;
			for(int i = 0;i < Power-1;i++)
			{
				Retval *= Value;
			}
			return Retval;
		}
		/// <summary>
		/// Converts the often preferred semi-circular data type to degrees.
		/// </summary>
		/// <param name="Semicircle">Contains the semi-circular value used by some GPS devices.</param>
		/// <returns>Double containing the degrees to convert.</returns>
		internal double SemicircleToDegrees(int Semicircle)
		{
			double dblRetVal = 0.0;
			double dblSemiCircle = 0.0;

			try
			{
				//Convert Garmin semicircles to decimal degrees
				dblSemiCircle = (double)Semicircle;
				dblRetVal = dblSemiCircle * (180.0 / (RaiseToPower(2, 31)));
			
			}
			catch(Exception ex)
			{
				throw ex;
			}		
			return dblRetVal;

		}
		/// <summary>
		/// Converts degrees to the often preferred semi-circular data type.
		/// </summary>
		/// <param name="Degrees">Double containing the degrees to convert.</param>
		/// <returns>Contains the semi-circular value used by some GPS devices.</returns>
		internal int DegreesToSemicircles(double Degrees)
		{
			try
			{
				//Convert degrees to Garmin Semicircles
				return (int)(Degrees * (double)(RaiseToPower(2, 31) / 180));
			}
			catch(Exception ex)
			{
				throw ex;
			}		
		}
		/// <summary>
		/// Converts Degrees to Radians.
		/// </summary>
		/// <param name="Degrees"></param>
		/// <returns></returns>
		internal static double DegreesToRadians(double Degrees)
		{
			try
			{
				return (Degrees * (PI / 180));
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}
		/// <summary>
		/// Converts Radians to Degrees.
		/// </summary>
		/// <param name="Radians"></param>
		/// <returns></returns>
        internal static double RadiansToDegrees(double Radians)
		{
			try
			{
				return (Radians * (180 / PI));
			}
			catch(Exception ex)
			{
				throw ex;
			}		
		}
		/// <summary>
		/// Limits an integer value to between 0 and 100.
		/// </summary>
		/// <param name="Value"></param>
		/// <returns></returns>
		internal int Limit(int Value)
		{
			return Limit(Value, 0, 100);
		}
		/// <summary>
		/// Limits an integer value to between the specified lower limit
		/// and 100.
		/// </summary>
		/// <param name="Value"></param>
		/// <param name="LowerLimit"></param>
		/// <returns></returns>
		internal int Limit(int Value,int LowerLimit)
		{
			return Limit(Value, LowerLimit, 100);
		}
		/// <summary>
		/// Limits an integer value to between the specified lower limit
		/// and the specified upper limit.
		/// </summary>
		/// <param name="Value"></param>
		/// <param name="LowerLimit"></param>
		/// <param name="UpperLimit"></param>
		/// <returns></returns>
		internal int Limit(int Value,int LowerLimit,int UpperLimit)
		{
			//-------------------------------------------------------------------------
			// ABSTRACT:     limits a value to the limits passed
			//
			// PARAMETERS:
			//
			//
			// RETURNS:
			//
			// DESCRIPTION:
			//
			//-------------------------------------------------------------------------
			
			
			try
			{
				//lower limit
				if(Value < LowerLimit)
					Value = LowerLimit;
				
				//upper limit, only if this has been set
				if(UpperLimit > 0)
				{
					if(Value > UpperLimit)
						Value = UpperLimit;
				}			
			}
			catch(Exception ex)
			{
				throw ex;
			}
			
			return Value;
		}
		/// <summary>
		/// Pads a string to the number of characters passed.
		/// </summary>
		/// <param name="String">The string to pad.</param>
        /// <param name="Chars">The number of charaters wide that the string should be padded to.
		/// If the string is longer than Chars then it is truncated.</param>
		/// <returns>String containing the padded result.</returns>
		internal string Pad(string String, int Chars)
		{
			int length = 0;
			string padded = "";

			try
			{
				length = String.Length;
				if(length < Chars)
				{
					padded = String + new String((char)32, Chars - length);
				}
				else if(length > Chars)
				{
					padded = String.Substring(0, Chars);
				}
				else
				{
					padded = String;
				}
			}
			catch(Exception ex)
			{
				throw ex;
			}
			return padded;
		}
		/// <summary>
		/// Pads/Limits a byte array to the number of characters passed.
		/// </summary>
		/// <param name="ByteArray">Byte Array to pad.</param>
		/// <param name="Bytes">
		/// Number of charaters wide that the array should
		/// be padded to. If the array is longer than Bytes then
		/// it is truncated.</param>
		/// <returns></returns>
		internal byte[] PadByte(byte[] ByteArray, int Bytes)
		{
			byte[] padded = new byte[Bytes];

			try
			{
				for(int index = 0; index < Bytes; index++)
				{
					if(index < ByteArray.Length)
						padded[index] = ByteArray[index];
				}
			}
			catch(Exception ex)
			{
				throw ex;
			}
			return padded;
		}
		
		internal string PadString(string sData)
		{
			return PadString(sData, "0");
		}
		/// <summary>
		/// Puts a leading character on a single character string.
		/// </summary>
		/// <param name="Data"></param>
		/// <param name="Pad"></param>
		/// <returns></returns>
		/// <remarks>
		/// Typically used to put a "0" in front of a single digit e.g. "1" becomes "01".
		/// </remarks>
		internal static string PadString(string Data, string Pad)
		{			
			try
			{
				//get the single pad character
				Pad = Pad.Substring(0,1);
				if(Data.Length <= 1)
					Data = string.Concat(Pad, Data);

				return Data;
			}
			catch(Exception ex)
			{
				throw ex;
			}		
		}
		/// <summary>
		/// This function concatenates two byte arrays into one.
		/// </summary>
		/// <returns></returns>
        internal byte[] ByteConcat(byte[] array1, byte[] array2)
        {

            byte[] data = null;
            int lenData1 = 0;
            int lenData2 = 0;

            try
            {
                //determine array lengths
                if (array1 != null)
                    lenData1 = array1.Length;
                if (array2 != null)
                    lenData2 = array2.Length;

                //create a new array to hold both incomming arrays
                data = new byte[lenData1 + lenData2];

                //copy the arrays
                if (lenData1 > 0)
                    Array.Copy(array1, 0, data, 0, lenData1);
                if (lenData2 > 0)
                    Array.Copy(array2, 0, data, lenData1, lenData2);

            }
            catch
            {
                //TraceLog.WriteError(e)
                throw;
            }

            return data;
        }
		/// <summary>
		/// Re-dimensions an array without losing its contents.
		/// </summary>
		/// <param name="Array">Array to be re-dimensioned.</param>
		/// <param name="NewDimension">New dimension, representing the number of elements
		/// e.g. a number of 4 would redimension the array to have 4 elements (0-3).</param>
		/// <returns></returns>
		internal static byte[] ReDimPreserve(byte[] Array,int NewDimension)
		{
			//re-dimensions a byte array and preserves the contents
			if(NewDimension <= 0 || NewDimension == 0)
				throw new ArgumentException(ERR_MSG_3010);

			byte[] bytNewArray = new byte[NewDimension];

			//copy any existing data
			if(Array != null)
				System.Array.Copy(Array,0,bytNewArray,0,Array.Length);
			
			return bytNewArray;
		}
		/// <summary>
		/// Re-dimensions an array without losing its contents.
		/// </summary>
		/// <param name="Array">Array to be re-dimensioned.</param>
		/// <param name="NewDimension">New dimension, representing the number of elements
		/// e.g. a number of 4 would redimension the array to have 4 elements (0-3).</param>
		/// <returns></returns>
		internal static string[] ReDimPreserveS(string[] Array, int NewDimension)
		{
			//re-dimensions a byte array and preserves the contents
			if(NewDimension <= 0 || NewDimension == 0)
				throw new ArgumentException(ERR_MSG_3011);

			string[] newArray = new string[NewDimension];

			//copy any existing data
			if(Array != null)
				System.Array.Copy(Array,0,newArray,0,Array.Length);
			
			return newArray;
		}
		/// <summary>
		/// Converts Feet to Meters.
		/// </summary>
		/// <param name="Feet"></param>
		/// <returns></returns>
		internal float FeetToMeters(float Feet)
		{
			return FeetToMeters(Feet, 0);
		}
		/// <summary>
		/// Converts Feet and Inches to Meters.
		/// </summary>
		/// <param name="Feet"></param>
		/// <param name="Inches"></param>
		/// <returns></returns>
		internal float FeetToMeters(float Feet, float Inches)
		{
			//use F suffix when specifying values for floats 
			return (0.305F*Feet) + (0.0254F*Inches);
		}
		/// <summary>
		/// Emulates the Visual Basic Timer() function.
		/// </summary>
		/// <returns></returns>
		internal static double Timer() 
		{
			DateTime dtTimer;

			dtTimer = DateTime.Now;
			return (double) dtTimer.Ticks % 711573504 / 1e+007;
		}
		/// <summary>
		/// Converts a byte to a byte array. Not used in final release.
		/// </summary>
		/// <param name="Data"></param>
		/// <returns></returns>
		internal byte[] ByteToByte(byte Data)
		{
			byte[] bytData = new byte[1];
			try
			{
				bytData[0] = Data;
				return bytData;
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}
		/// <summary>
		/// Converts a short to a byte array.
		/// </summary>
		/// <param name="Data"></param>
		/// <returns></returns>
		internal static byte[] ShortToByte(short Data)
		{
			return ShortToByte(Data, false);
		}
		/// <summary>
		/// Converts a short to a byte array.
		/// </summary>
		/// <param name="Data"></param>
        /// <param name="SingleByte"></param>
		/// <returns></returns>
		internal static byte[] ShortToByte(short Data, bool SingleByte)
		{

			byte[] bytData;

			try
			{
				if(SingleByte)
				{
					bytData = new byte[1];
					bytData[0] = (byte)(Data % 256); //modulus (remainder)
				}
				else
				{
                    //[jn 2.7.9]
                    bytData = BitConverter.GetBytes(Data);
                }
			}
			catch(Exception ex)
			{
				throw ex;
			}
			return bytData;
		}
		/// <summary>
		/// This function returns a string up to the first null.
		/// </summary>
		/// <param name="String"></param>
		/// <returns></returns>
		internal string TrimNull(string String)
		{			
			try
			{
				//get rid of any leading or trailing spaces
				String = String.Trim();
				
				//add a null to the end of the string just in case the 
				//string doesn't already contain one
				string.Concat(String,"\0");
				
				//TODO: Remove ref to VB function
				//get the left part of the string up to the first null,
				//(or the null we have added if there isn't one)
				return Microsoft.VisualBasic.Strings.Left(String, String.IndexOf("\0") - 1);
			}

			catch(Exception ex)
			{
				throw ex;
			}		
		}
        /// <summary>
        /// Converts and integer to a byte array containin one byte.
        /// </summary>
        /// <param name="Data"></param>
        /// <returns></returns>
        internal byte[] IntToByte(int Data)
        {
            return IntToByte(Data, false);
        }
        /// <summary>
		/// Converts and integer to a byte array.
		/// </summary>
		/// <returns></returns>
		internal byte[] IntToByte(int Data, bool SingleByte)
		{
			const int DATA_SIZE = 4;
			
			byte[] bytData = new byte[DATA_SIZE];

            try
            {
                if (SingleByte)
                {
                    bytData = new byte[1];
                    bytData[0] = (byte)(Data % 256); //modulus (remainder)
                }
                else
                {
                    bytData = BitConverter.GetBytes(Data);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
		    return bytData;
		}
		/// <summary>
		/// Converts a byte array to a string.
		/// </summary>
		/// <param name="Data"></param>
		/// <param name="Position"></param>
		/// <param name="Length"></param>
		/// <returns></returns>
		internal string ByteToString(byte[] Data, int Position, int Length)
		{
			return ByteToString(Data, Position, Length, true, true, false);
		}

		/// <summary>
		/// Converts a byte array to a string.
		/// </summary>
		/// <param name="Data"></param>
		/// <param name="Position"></param>
		/// <param name="Length"></param>
        /// <param name="ReplaceNull"></param>
        /// <param name="Trim"></param>
		/// <returns></returns>
		internal string ByteToString(byte[] Data, int Position, int Length, bool ReplaceNull, bool Trim)
		{
			return ByteToString(Data, Position, Length, ReplaceNull, Trim, false);
		}

		/// <summary>
		/// Converts a byte array to a string.
		/// </summary>
		/// <param name="Data">Byte array to process</param>
		/// <param name="Position">Position of start of string</param>
		/// <param name="Length">Length of string</param>
		/// <param name="ReplaceNull">Boolean indicating whether any nulls chr(0) are to be replaced</param>
		/// <param name="Trim">Boolean to indicate wether leading and trailing spaces</param>
        /// <param name="UniCode">Boolean to convert to unicode characters.</param>
		/// <remarks>
		///	If the bReplaceNull is false the left most part of the string to the first NULL will be returned.
		///	The bUnicode Flag should be set to false if the byte array is already a unicode sequence of characters
		/// </remarks>
		/// <returns></returns>
		internal string ByteToString(byte[] Data, int Position, int Length, bool ReplaceNull, bool Trim, bool UniCode)
		{

			byte[] bytTemp = null;
			string sTemp = "";
			string sReplace = " ";
			//			int iIndex = 0;

			try
			{
				//create the temporary storage for the string
				bytTemp = new byte[Length];
				
				//populate the temporary storage
				bytTemp = CopyByteArray(Data, Position, Length);
				
				//convert the byte array to either a unicode String or a string of bytes
				if(UniCode)
				{
					//should be a even number of bytes as its unicocde
					sTemp = System.Text.UnicodeEncoding.Unicode.GetString(bytTemp);
				}
				else
				{
					sTemp = System.Text.Encoding.ASCII.GetString(bytTemp);
				}
				
				//replace any nulls if so desired and return the string
				if(ReplaceNull)
				{
					sTemp = sTemp.Replace("\0",sReplace);
				}
			
				//trim leading and trailing spaces if desired
				if(Trim)
					sTemp = sTemp.Trim();
			}
		
			catch(Exception ex)
			{
				throw ex;
			}
			return sTemp;
		}
		/// <summary>
		/// Converts a byte array to a double.
		/// </summary>
		/// <param name="Data"></param>
		/// <param name="Position"></param>
		/// <returns></returns>
		internal double ByteToDouble(byte[] Data, int Position)
		{

			const int DATA_SIZE = 8;

			double data = 0;

			try
			{
				if(Position <= Data.GetUpperBound(0) - (DATA_SIZE - 1))
					data = BitConverter.ToDouble(Data, Position);
			}
			catch(Exception ex)
			{
				throw ex;
			}

			return data;

		}
		/// <summary>
		/// Converts a byte to a short.
		/// </summary>
		/// <param name="Data"></param>
		/// <param name="Position"></param>
		/// <returns></returns>
		internal short ByteToShort(byte[] Data, int Position)
		{

			const int DATA_SIZE = 2;
			const int MAXINT = 32767;
			const int OFFSET = 65536;
			
			int data = 0;
			
			try
			{
				if(Position <= Data.GetUpperBound(0) - (DATA_SIZE - 1))
				{
					data = BitConverter.ToInt16(Data, Position);
				}

				//ensure its signed - at this point iData could contain unsigned integer if this
				//is the case idata cannot be assigned to any other integer
				if(data <= MAXINT)
				{
					return (short)data;
				}
				else
				{
					return (short)(data - OFFSET);
				}				
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}
        /// <summary>
        /// Converts a byte array to an integer.
        /// </summary>
        /// <param name="Data"></param>
        /// <param name="Position"></param>
        /// <returns></returns>
        internal uint ByteToUInt(byte[] Data, int Position)
        {

            const int DATA_SIZE = 4;

            uint data = 0;
            try
            {
                //check that the position is OK
                if (Position <= (Data.GetUpperBound(0) - (DATA_SIZE - 1)))
                    data = BitConverter.ToUInt32(Data, Position);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return data;
        }
        /// <summary>
		/// Converts a byte array to an integer.
		/// </summary>
		/// <param name="Data"></param>
		/// <param name="Position"></param>
		/// <returns></returns>
		internal int ByteToInt(byte[] Data, int Position)
		{

			const int DATA_SIZE = 4;

			int data = 0;
			try
			{
				//check that the position is OK
				if(Position <= (Data.GetUpperBound(0) - (DATA_SIZE - 1)))
					data = BitConverter.ToInt32(Data, Position);
			}
			catch(Exception ex)
			{
				throw ex;
			}
			return data;
		}
		/// <summary>
		/// Converts a byte array to a single.
		/// </summary>
		/// <param name="Data"></param>
		/// <param name="Position"></param>
		/// <returns></returns>
		internal float ByteToSingle(byte[] Data, int Position)
		{

			const int DATA_SIZE = 4;

			float data = 0;

			try
			{
				if(Position <= (Data.GetUpperBound(0) - (DATA_SIZE - 1)))
					data = BitConverter.ToSingle(Data, Position);
			}
			catch(Exception ex)
			{
				throw ex;
			}
			return data;
		}
		/// <summary>
		/// Converts a string to a byte array.
		/// </summary>
		/// <param name="Data"></param>
		/// <returns></returns>
		internal byte[] StringToByte(string Data)
		{
			//TODO: Why is this static
			return StringToByte(Data,false);
		}
		/// <summary>
		/// Converts a string to a byte array.
		/// </summary>
		/// <param name="Data"></param>
		/// <param name="NullTerminate"></param>
		/// <returns></returns>
		internal byte[] StringToByte(string Data, bool NullTerminate)
		{
			//TODO: Why is this static
			int iIndex = 0;
			int iLength = 0;
			byte[] bytData = null;

			try
			{
				iLength = Data.Length;
	
				if(iLength > 0)
				{
					if(NullTerminate)
					{
						bytData = new byte[iLength + 1];

						for(iIndex = 0;iIndex < (bytData.Length - 1);iIndex++)
						{
							//TODO: Remove ref to VB
							bytData[iIndex] = (byte)Microsoft.VisualBasic.Strings.Asc(Microsoft.VisualBasic.Strings.Mid(Data, iIndex + 1, 1));
						}

						//add the null
						bytData[iLength] = 0;
					}
					else
					{
						bytData = new byte[iLength];
				
						for(iIndex = 0;iIndex < bytData.Length;iIndex ++)
						{
							bytData[iIndex] = (byte)Microsoft.VisualBasic.Strings.Asc(Microsoft.VisualBasic.Strings.Mid(Data, iIndex + 1, 1));
						}
					}
				}
                //[jn] added following Benji Yeagers comments 
                else
                {
                    if (NullTerminate)
                    {
                        bytData = new byte[1];
                        bytData[0] = 0;
                    }
                }
			}
			catch (Exception ex)
			{
				//TraceLog.WriteError(e)
				throw ex;
			}

			return bytData;
		
		}
		/// <summary>
		/// Converts a Singe to a byte array.
		/// </summary>
		/// <param name="Data"></param>
		/// <returns></returns>
		internal byte[] SingleToByte(float Data)
		{
			
			const int DATA_SIZE = 4;
			
			byte[] bytData = new byte[DATA_SIZE];

			try
			{
				return BitConverter.GetBytes(Data);
			}
			catch(Exception ex)
			{
				throw ex;
			}		
		}
		/// <summary>
		/// Converts a double to a byte array.
		/// </summary>
		/// <param name="Data"></param>
		/// <returns></returns>
		internal byte[] DoubleToByte(double Data)
		{
		
			const int DATA_SIZE = 8;
		
			byte[] bytData = new byte[DATA_SIZE];

			try
			{
				return BitConverter.GetBytes(Data);
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}
		/// <summary>
		/// Copies a byte array from one array to another. Starting from the 
		/// specified position in the source array (zero based).
		/// </summary>
		/// <param name="Source"></param>
		/// <param name="StartPosition"></param>
		/// <param name="NoOfBytes"></param>
		/// <returns></returns>
		internal byte[] CopyByteArray(byte[] Source, int StartPosition,int NoOfBytes)
		{
			int intIndex = 0;
			byte[] bytTemp = new byte[NoOfBytes];
			try
			{
				for(intIndex = 0; intIndex < NoOfBytes; intIndex++)
				{
					bytTemp[intIndex] = Source[StartPosition + intIndex];
				}				
			}
			catch(Exception ex)
			{
				TraceLog.WriteError(ex);
				throw ex;
			}
			return bytTemp;
		}

		#endregion


	}
}
